/////////////////////////////////////////////////////////////////////////
//
// Amuse Engine SDK - core/containers
// Copyright (c) 2014.  All Rights Reserved
//
// File:		AETQueue.h
// Author:		Gianluca Belardelli
// Date:		01/06/2014
//
/////////////////////////////////////////////////////////////////////////
#ifndef _AETQUEUE_H_
#define _AETQUEUE_H_

/// A FIFO circular queue
template <typename T>
class AETQueue
{
// Methods
private:
	// queue memory management
	T		*m_lpData;
	AEINT32	m_nCapacity; 

	// queue FIFO management
	AEINT32 m_nHead;
	AEINT32 m_nTail;
	AEINT32 m_nElementsInUse;

// Members
private:
	AE_FORCEINLINE void _increaseCapacity( void );

	// frees the internal storage
	AE_FORCEINLINE void _releaseMemory( void );

public:
	AE_DECLARE_NONVIRTUAL_CLASS_ALLOCATOR( TOBEDEFINED, AETQueue );

	/// Creates a zero length queue.
	AETQueue( void );

	/// Creates an queue of capacity n. All elements are uninitialized.
	AETQueue( AEINT32 nCapacity );

	/// Deallocates queue memory.
	~AETQueue( void );

	// Allocates more internal queue storage
	AE_FORCEINLINE void SetCapacity( AEINT32 nCapacity );

	/// Pushes a new element to the back of the queue and expands the storage if necessary.
	AE_FORCEINLINE void Enqueue( const T &tElem );

	/// Pushes a new element to the front of the queue and expands the storage if necessary.
	AE_FORCEINLINE void EnqueueInFront( const T &tElem );

	/// Fills in the data with the element at the front of the queue
	AE_FORCEINLINE void Dequeue( T &tData );

	/// Fills in the data with the element at the front of the queue but does not modify the queue
	AE_FORCEINLINE void Peek( T &tData ) const;

	/// Clears the queue
	AE_FORCEINLINE void Clear( void );

	/// Are there any elements left on the queue?
	AE_FORCEINLINE AEBOOL32 IsEmpty( void ) const;

	/// How many elements are on the queue?
	AE_FORCEINLINE AEINT32 GetSize( void ) const;

	/// Returns the total capacity of the queue storage
	AE_FORCEINLINE AEINT32 GetCapacity( void ) const;

	/// Read-only access to the data pointer
	AE_FORCEINLINE const T* GetData( void ) const;

	/// Read-only access to the nth element from the front of the queue
	AE_FORCEINLINE const T &GetElement( AEINT32 nIdx ) const;

	/// For internal use
	AE_FORCEINLINE AEINT32 GetHead( void ) const;
	AE_FORCEINLINE AEINT32 GetTail( void ) const;
};

#include "AETQueue.inl"

#endif // _AETQUEUE_H_
